/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package it.polimi.meteocal.control;

import it.polimi.meteocal.entity.Event;
import it.polimi.meteocal.entity.Forecast;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.Schedule;
import javax.ejb.Singleton;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.TypedQuery;
import net.aksingh.java.api.owm.DailyForecastData;

/**
 *
 * @author paolo
 */
@Singleton
public class ThreeDayService {

    private final int badMinRange = 800;
    private final int badMaxRange = 804;
    @EJB
    private MessageManager mm;
    @EJB
    private UserManager um;
    @PersistenceContext
    private EntityManager em;
    @EJB
    private ForecastManager fm;

    /**
     * scheduled method execute once a day at 0:11 that control all the outdoor
     * event of one day that will take place after three day checking if there
     * are bad condition and sending a message to the author of the event if
     * exist a good day in the next 10 days
     */
    @Schedule(dayOfWeek = "*", hour = "0", minute = "11")
    public void threeDayCheck() {
        System.out.println("*********THREE DAY CHECK**********");
        TypedQuery<Forecast> forecastQuery = em.createQuery("SELECT f FROM Forecast f WHERE f.forecastDate = :day", Forecast.class);
        GregorianCalendar cal = new GregorianCalendar();
        cal.add(Calendar.DAY_OF_MONTH, 3);
        System.out.println(cal.getTime());
        forecastQuery.setParameter("day", cal);
        for (Forecast f : forecastQuery.getResultList()) {
            System.out.println("***forecast to check: " + f.getCity() + " " + f.getForecastDate().getTime());
            if (badMinRange <= f.getForecast() && f.getForecast() <= badMaxRange) {
                System.out.println("GOOD WEATHER");
            } else {
                System.out.println("BAD WEATHER");
                Date goodDay = this.findGoodDay(f.getCity());
                if (goodDay == null) {
                    System.out.println("no good day available");
                } else {
                    System.out.println("good day available " + goodDay);
                    for (Event e : f.getEventCollection()) {
                        System.out.println("******event related to to the forecast: " + e.getName() + " " + e.getCity() + " " + e.getStartDate().getTime());
                        ArrayList<String> user = new ArrayList<>();
                        user.add(e.getAuthor().getEmail());
                        mm.addInvitedMessage(e, user, mm.createMessage(e, 4, "" + goodDay));
                    }
                }
            }
        }
    }

    /**
     * chek if exist a good day for a city from the day after
     *
     * @param city city to check forecast
     * @return the day in wich there is good condition, null otherwise
     */
    public Date findGoodDay(String city) {
        List<DailyForecastData.Forecast> cityForecast = fm.getCityForecast(city);
        if (cityForecast == null) {
            return null;
        } else {
            for (DailyForecastData.Forecast forecast : cityForecast) {
                if (badMinRange <= forecast.getWeather_List().get(0).getWeatherCode() && forecast.getWeather_List().get(0).getWeatherCode() <= badMaxRange) {
                    GregorianCalendar cal = new GregorianCalendar();
                    GregorianCalendar forDate = new GregorianCalendar();
                    forDate.setTime(forecast.getDateTime());
                    if (forDate.get(Calendar.DAY_OF_YEAR) != cal.get(Calendar.DAY_OF_YEAR)) {
                        return forecast.getDateTime();
                    }
                }
            }
        }
        return null;
    }
}
